unit ThSort;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, SortThds, UMono, UMonoIntf, UScriptClass;

type
  TThreadSortForm = class(TForm)
    BubbleSortBox: TPaintBox;
    SelectionSortBox: TPaintBox;
    QuickSortBox: TPaintBox;
    Bevel1: TBevel;
    Bevel2: TBevel;
    Bevel3: TBevel;
    StartBtn: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    OpenDialog1: TOpenDialog;
    Label4: TLabel;
    Label5: TLabel;
    procedure StartBtnClick(Sender: TObject);
    procedure BubbleSortBoxPaint(Sender: TObject);
    procedure SelectionSortBoxPaint(Sender: TObject);
    procedure QuickSortBoxPaint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    ThreadsRunning: Integer;
    procedure IdleProc(Sender: TObject; var Done: Boolean);
    procedure RandomizeArrays;
    procedure ThreadDone(Sender: TObject);
  public
    procedure PaintArray(Box: TPaintBox; const A: TIntSortArray);
  end;

var
  ThreadSortForm: TThreadSortForm;

implementation

uses UMonoRTTIInv;


{$R *.dfm}

var
  ArraysRandom: Boolean;
  BubbleSortArray, SelectionSortArray, QuickSortArray: TIntSortArray;

{ TThreadSortForm }

procedure TThreadSortForm.PaintArray(Box: TPaintBox; const A: TIntSortArray);
var
  I: Integer;
begin
  with Box do
  begin
    Canvas.Pen.Color := clRed;
    for I := 0 to length(a)-1 do
      PaintLine(Canvas, I, A[I]);
  end;
end;

procedure TThreadSortForm.BubbleSortBoxPaint(Sender: TObject);
begin
  PaintArray(BubbleSortBox, BubbleSortArray);
end;

procedure TThreadSortForm.SelectionSortBoxPaint(Sender: TObject);
begin
  PaintArray(SelectionSortBox, SelectionSortArray);
end;

procedure TThreadSortForm.QuickSortBoxPaint(Sender: TObject);
begin
  PaintArray(QuickSortBox, QuickSortArray);
end;

procedure TThreadSortForm.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown:= DebugHook <> 0;
  SetMonoPath('C:\Program Files\Mono-2.8.2\bin');
  InitMono;

  RandomizeArrays;
end;

procedure TThreadSortForm.FormShow(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    MonoJit := TMonoJit.Create('v4.0.30319', OpenDialog1.FileName, '0', 0);
    MonoJit.AddInternalCall('Mono4Delphi','TProxyAnyIntf', 'DelphiInvoke', @DelphiRTTIInvoke);
    MonoJit.AddClassMap(TObject, 'Mono4Delphi.ITObject');
    MonoJit.AddClassMap(TSortThread, 'Mono4Delphi.ITSortThread');

    MonoJit.LoadAssembly;
    Application.OnIdle := Self.IdleProc;
  end;
end;

procedure TThreadSortForm.IdleProc(Sender: TObject; var Done: Boolean);
begin
  Label4.Caption := 'used '+ IntToStr(mono_gc_get_used_size())+' bytes';
  Label5.Caption := 'heap '+IntToStr(mono_gc_get_heap_size())+' bytes';
end;

procedure TThreadSortForm.StartBtnClick(Sender: TObject);
begin
  RandomizeArrays;
  ThreadsRunning := 3;
  with TSortThread.Create(BubbleSortBox, BubbleSortArray, OpenDialog1.FileName, 'Mono4Delphi', 'BubbleSort') do
    OnTerminate := ThreadDone;
  with TSortThread.Create(SelectionSortBox, SelectionSortArray, OpenDialog1.FileName, 'Mono4Delphi', 'SelectionSort') do
    OnTerminate := ThreadDone;
  with TSortThread.Create(QuickSortBox, QuickSortArray, OpenDialog1.FileName, 'Mono4Delphi', 'QuickSort') do
    OnTerminate := ThreadDone;
  StartBtn.Enabled := False;
end;

procedure TThreadSortForm.RandomizeArrays;
var
  I: Integer;
begin
  if not ArraysRandom then
  begin
    Randomize;
    setlength(BubbleSortArray, 114);
    for I := 0 to Length(BubbleSortArray)-1 do
      BubbleSortArray[I] := Random(170);
    SelectionSortArray := BubbleSortArray;
    QuickSortArray := BubbleSortArray;
    ArraysRandom := True;
    Repaint;
  end;
end;

procedure TThreadSortForm.ThreadDone(Sender: TObject);
begin
  Dec(ThreadsRunning);
  if ThreadsRunning = 0 then
  begin
    StartBtn.Enabled := True;
    ArraysRandom := False;
  end;
end;

initialization
finalization
  MonoJit.Free;
end.
